home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cljul90.zip / LITERATE.CPP < prev    next >
Text File  |  1990-06-19  |  28KB  |  632 lines

  1. Literate C++
  2.  
  3. Marco S. Hyman
  4. uucp:  ...!pacbell!dumbcat!marc
  5.  
  6. Next time you're feeling bored ask a group of programmers to define good
  7. program documentation -- then duck before every volume of The Art of Computer
  8. Programming is thrown your way.  The extremes are easy to identify.  There is
  9. usually at least one in the group insisting that the only documentation ever
  10. needed is the source, the whole source, and nothing but the source.  At the
  11. other end of the spectrum will be the programmer bent under weighty volumes of
  12. requirements analysis documents, system design documents, HIPO charts, data
  13. flow diagrams, data dictionaries, structure charts, and, of course, source
  14. listings.
  15.     One of the reasons for such diverse opinions is that each programmer is
  16. likely to have a different documentation goal.  Some programmers want to
  17. explain algorithms, others want to show data flow and state transitions. There
  18. are also those that do the bare minimum required by the organization they work
  19. for.  This last group can't see any purpose in writing documentation, so
  20. perhaps we should state one:
  21.     "The purpose of program documentation is to provide enough information for
  22. another programmer to understand and maintain the program."
  23.     If this purpose seems a bit altruistic substitute ``another programmer''
  24. with ``you, after not looking at the program for a year.'' The purpose is just
  25. as strong and certainly hits closer to home.
  26.     But what about C++ class documentation?  One of the advantages of C++ and
  27. object-oriented programming is that it leads to code re-use.  However, a
  28. programmer is not likely to re-use code when its function is a mystery. Forcing
  29. another programmer to look at your implementation to discover what your code
  30. does is not polite.  It leads to your code being tossed in favor of code the
  31. other guy understands.  Code is not re-usable until it's documented.
  32.     "The purpose of class documentation is to provide enough information for
  33. another programmer to use the class and member functions of the class."
  34.     Two levels of documentation are needed; the first level for users of a
  35. class and the second level for maintainers of the class.  Class users need
  36. something like the pages in your C library reference manual. Class maintainers
  37. need to know the algorithms used and WHY the code is the way it is.  Both the
  38. code and the class documentation will convey WHAT the class does.
  39.  
  40. Literate Programming
  41.     Don Knuth conceived the idea of programs as works of literature and created
  42. ``Literate Programming'' (see sidebar) as a method of explaining to programmers
  43. what the computer was to do.  In Knuth's implementation a program is written in
  44. WEB, a language consisting of both TeX text and Pascal text.  The combined text
  45. is processed by two programs, TANGLE and WEAVE, to produce both Pascal source
  46. code and TeX formatted documentation.
  47.     There are many advantages of keeping the documentation and the code in the
  48. same file.  A programmer is more likely to update both when both are on the
  49. screen at the same time, thus keeping the program and documentation in sync. It
  50. also becomes impossible to loose the documentation (without also losing the
  51. source).  With the proper tools a pretty printed version of the source can be
  52. included in the documentation.  Most important, the programmer is encouraged to
  53. think about both documentation and code.  This usually has a side effect of
  54. improving both.
  55.     To see if the literate programming paradigm can be stretched to include C++
  56. I propose Literate C++ (lc++)*1.  As shown in figure 1 an lc++ input file
  57. (file.lc) will be used to create both a C++ header file (file.h) and a C++
  58. source file (file.cc).  The lc++ input file (file.lc) can also be processed to
  59. create a library manual page (file.3) and a class documentation file
  60. (file.doc).
  61.     An lc++ language has been designed and a header and source file extraction
  62. program, named lcpp, has been prototyped in awk.*2  They are both described
  63. below.  My goal is to use the prototype program for a while, refining the lc++
  64. language as it is used to generate the second generation extraction tool in
  65. lc++.  The next step will be to determine a good format for both types of
  66. documentation and the creation of the documentation extraction tools.
  67.  
  68. The lc++ Language
  69. The lc++ commands are listed in figure 2.  Each command starts with an at sign
  70. (@) and currently must be the first token on a line, although this is likely to
  71. change.
  72.     Each lc++ input (.lc) file creates one header file and one source file.  If
  73. multiple headers are required, for example, then each must have its own lc++
  74. file.  One of the purposes of the awk prototype is to determine if this
  75. limitation is reasonable.
  76.     The .lc file contains three sections.  The first section consists of all
  77. text and commands prior to the @specification command.  Text in this section is
  78. ignored by both the code and documentation extraction tools.  Commands usually
  79. found in this section are @title and @copyright.
  80.     The second section of the file starts with @specification.  Code and text
  81. in the specification section are used to create the header (.h) file and the
  82. library man page (.3) file.  The code in this sections defines classes and
  83. declares member functions.
  84.     The final section starts with the @implementation command.  This section is
  85. used to define the member functions declared in the section sections.  The text
  86. in this section is free form and used to explain what is being done and why.
  87. Code and text in this section create the source (.cc) file and the
  88. documentation (.doc) file.  @inline commands will cause code to be added to the
  89. end of the header file. A description of each command follows.
  90.     @title: The @title command causes a title, perhaps including version
  91. information, to be written to both the .h and the .cc output files. Along with
  92. the title is a canned notice that explains that the output files should not be
  93. modified directly, but that changes should be applied to the input (.lc) file
  94. and lc++ run again to generate new output files.
  95.     @copyright: The @copyright statement is written to both output files.
  96. Comment delimiters must be supplied.  This is not done automatically as
  97. different authors prefer different commenting styles.  The copyright section is
  98. also a good place to include a change log, such as that built by RCS or any
  99. other version control system you may be using.
  100.     @code: The @code command enables output.  The location of the output, .h
  101. file or .cc file, depends upon the current mode (specification or
  102. implementation). All lines following the @code line are written to the current
  103. file.  Output continues until a command that disables output is encountered.
  104. An @code is not always required for output.  The @copyright command above, for
  105. example, enables output by default.
  106.     @text: The @text command disables .h or .cc output and signifies the
  107. beginning of documentation.  The text will be written to the library manual
  108. page (.3) file when @text is seen in the @specification section.  Text will be
  109. written to the documentation (.doc) file when seen in the implementation
  110. section.  Alternating @text and @code commands are often seen as the author
  111. goes back and forth between coding and documenting.
  112.     @specification: The @specification command selects specification mode. In
  113. specification mode @code output is written to the .h file.  Classes are defined
  114. in this mode and class members are declared.  @code output is written to the .h
  115. file immediately.  Other output, such as class definitions and member
  116. declarations, are not written until the specification mode ends. Output is not
  117. enabled by the @specification command.  The mode is ended by end of the lc++
  118. input (.lc) file or by an @implementation command.
  119.     @class: The @class command starts the definition of a new class.  Classes
  120. are always output in the order that the @class command is found in the lc++
  121. input (.lc) file.  No output is done until the specification section of the .lc
  122. file is finished.  If circular class definitions are required use a class x;
  123. declaration in an @code block before the @class definition.
  124.     @base: The @base command declares the base classes that make up a class.
  125. The syntax of the command is @base @<classname> <base class description>. The
  126. @<classname> is optional.  By default, an @base command adds a base class to
  127. the last class defined with the @class command.  Because it may be easier to
  128. document related classed by bouncing between them it is possible to add a base
  129. class to any previously defined class by using the @<classname> syntax.
  130. Example:
  131.  
  132. @class Class1                // defines Class1
  133. @class Class2                // defines Class2
  134. @base virtual public Base2   // adds Base2 as a base class of Class2
  135. @base @Class1 public Base1   // adds Base1 as a base class to Class1
  136. @base private Base2p         // adds Base2p as another base class
  137.                              // to Class2 (the last defined class).
  138.  
  139.     @public, @protected, and @private: These three command add members to the
  140. current class.  Like the @base command members can be added to a previous named
  141. class by adding an @<classname> after the @public, @protected, or @private
  142. command.  The text on the command line after the command will be copied into
  143. the class definition.  Proper C++ syntax must be followed.
  144.     The text following the command should explain when to use the member and
  145. what the member does.  Of course, this pertains to member functions much more
  146. so that data members.  How member functions are implemented is *not*
  147. appropriate subject matter here.  This is still part of the specification. The
  148. implementation could vary many ways and still meet the specification. This text
  149. is *not* added to the header file.
  150.     @requires: The @requires command introduces text that describes caller
  151. requirements.  That is, if the requirements are not followed than the called
  152. function is not required to work.  Examples of @requires would be that only
  153. positive numbers are passed to a square root function. This command always
  154. pertains to the last @public, @protected, or @private command found in the lc++
  155. input (.lc) file.
  156.     @effects: This command introduces a very brief description of what the
  157. member function does, i.e. what is the effects of calling the member function.
  158. The description is used to generate class documentation.  This command always
  159. pertains to the last @public, @protected, or @private command found in the lc++
  160. input (.lc) file.
  161.     See Abstraction and Specification in Program Development by Liskov and
  162. Guttag on specifying procedures by use of a requires and an effects clause.
  163. They also use a modifying clause which could be added to lc++.
  164.     @implementation: The implementation command forces classes defined to be
  165. written to the header (.h) file and switches @code output to be written to the
  166. source (.cc) file.  All output, except for @inline (see below) will now be
  167. written to the source file. Text written after the @implementation command
  168. should discuss implementation details; more of the *how* than the *why*.
  169.     @member: The @member command starts the definition of a member function.
  170. All lines following the @member command will be copied to the source (.cc)
  171. file.  The command will be used when the documentation extraction programs are
  172. written. In the source extraction program it acts as an @code.
  173.     @inline: The @inline command adds the lines following the command to the
  174. header (.h) file.  The member function should have been declared as inline in
  175. the specification section of the file.  This is not verified, however, and can
  176. lead to problems.  For this reason future versions of the language will not use
  177. this keyword.
  178.  
  179. The AWK extraction program
  180. Listing 1 is lcpp, the awk program used to process the lc++ input file. It uses
  181. the features of new awk, as described in The AWK Programming Language by Aho,
  182. Kernighan, and Weinberger.  The program is fairly simple and should be easy to
  183. understand.
  184.     Two arrays, class and className, are used to associate a class name with a
  185. class number.  The array class returns a class number when indexed by a name.
  186. The array className returns a name when indexed by a number.
  187.     The only tricky bit of coding is in the use of awk's associative arrays to
  188. force classes and member functions to be output in the same sequence they were
  189. input.  The use of the member array illustrates the use. Whenever a new class
  190. is defined three entries are added to the member array for the class using the
  191. class number classNum, member[classNum, "public"],  member[classNum,
  192. "protected"], and member[classNum, "private"].  The three entries are
  193. initialized to 0.  This entry is then used as an index into the array when a
  194. member definition occurs.  A public member definition would be added at
  195. member[classNum, "public", member[classNum, "public"]].  Note that this entry
  196. uses three indexes and the third is the current count.  The count is
  197. incremented after the entry is added.  The functions doClass and doMembers use
  198. these embedded counts to control printing.
  199.  
  200. A Short Example
  201.     Listing 2 contains a short example of literate C++.  The code doesn't do
  202. anything except to illustrate some of the features of the language.  Note how
  203. descriptive text can be placed anywhere in the file. When processed by awk and
  204. lcpp two output files are created.  With the input file named test.lc the
  205. output files are named test.h (listing 3) and test.cc (listing 4).  The command
  206. line used to generate these files was
  207.  
  208. awk -f lcpp test.lc
  209.  
  210. but this may vary between operation systems and versions of awk.
  211.     The definition of Literate C++ is not complete.  Non-member functions are
  212. not handled and inline member functions must be declared as inline in too many
  213. places.  Also, little thought has been given to how documentation should be
  214. typeset.  Documentation requirements are sure to force changes to the
  215. definition.  With use, this prototype will help show what other changes need to
  216. be made to the language.
  217.     Will literate C++ work?  Think of all the programs you've had to learn over
  218. the years.  Now think of those that have been the easiest to understand.
  219. Weren't the ones easiest to understand accompanied by articles in Computer
  220. Language, or Dr. Dobbs, or Byte: code and text -- a literate programming style.
  221.  
  222. Marco S. Hyman is a principal engineer, designing and writing software for a
  223. company in San Francisco.  C++ and object-oriented programming are hobbies he
  224. pursues at home.   He can be reached via e-mail (UUCP) at
  225. ...!pacbell!dumbcat!marc.
  226.  
  227. Bibliography
  228.     Aho, A.V, B.W. Kernighan, and P.J. Weinberger, The AWK Programming
  229. Language, Addison-Wesley, Reading, Mass. (1988).
  230.     Liskov, B., and J. Guttag, Abstraction and Specification in Program
  231. Development, MIT Press, Cambridge, Mass. (1986).
  232.  
  233.     *1 Note: By rights this should be called C++WEB or WEB++.  I thought of
  234. lc++ first and like the name so haven't changed it.
  235.     *2 Note: Lcpp is written in awk and requires new awk (nawk for old UNIX
  236. hands.) I believe the DOS ports of awk are new awk compatible.
  237.  
  238.  
  239. Sidebar: Literate Programming
  240.     Literate Programming is the name given by Donald Knuth to a programming
  241. language and documentation system built around the idea that a program can be
  242. considered a work of literature. It is Knuth's belief that a ``practitioner of
  243. literate programming can be regarded as an essayist, whose main concern is with
  244. exposition and excellence of style.'' These main concerns emphasize the goal of
  245. a literate program:  explaining to another programmer what the computer is to
  246. do.
  247.     Knuth's literate programming is implemented in WEB, a language that
  248. combines the features of two other languages, TeX and PASCAL. WEB programs are
  249. descriptions of software systems. A WEB description is processed by two other
  250. programs, TANGLE and WEAVE, to produce a PASCAL source file and a TeX input
  251. file. When the TeX input file is processed by TeX the output is a ``pretty
  252. printed'' version of the program with supporting documentation.
  253.     WEB files are composed of modules with each module consisting of three
  254. parts: TeX explanatory material, definitions (WEB adds simple macros to
  255. PASCAL), and PASCAL code.
  256.     Each module is more or less self-contained and should not be so long that
  257. its structure is hidden in its length and complexity.  Modules are often a few
  258. lines long, they are rarely longer than a page.
  259.     Other versions of WEB or WEB-like languages are also in use.  CWEB is
  260. similar to WEB but the output is TeX and C.  (This is not to be confused with
  261. the WEB2C tool that converts original WEB to C code.)  loom is a preprocessor
  262. written by Janet Incerpi and Robert Sedgewick and used in preparation of
  263. Sedgewick's book Algorithms (Addison-Wesley, Reading, Mass., 1983).
  264.     The Communications of the ACM has a sometimes column on literate
  265. programming moderated by Christopher J. Van Wyk of AT&T Bell Laboratories.  See
  266. the July 1987, December 1987, December 1988, June 1989, and September 1989
  267. issues.  The latest column described the language SPIDER which is used to
  268. generate WEBs for other languages.
  269.  
  270. For more information see also:
  271.     Bently, J., D. Knuth, and D. McIlroy, ``Programming Perls: A Literate
  272. Program,'' Communications of the ACM, 29,6 (June 1986), 471-483
  273.     Knuth, D., ``Literate Programming,'' Computer Journal, 27,2 (1984), 97-111
  274.     Knuth, D., The WEB System of Structured Documentation, Stanford Computer
  275. Science Report CS980 (September 1983).
  276.  
  277. Figure 1
  278.  
  279.                      ..............
  280.                      . lc++ input .
  281.                      . (file.lc)  .
  282.                      ..............
  283.                            |
  284.             .....................................
  285.             |                                   |
  286.       lcpp awk script                   some future program
  287.             |                                   |
  288.       ..............                   ....................
  289.       |            |                   |                  |
  290. ............ .............    ................... ..................
  291.  C++      . . C++       .    . class           . . class          .
  292. . Header   . . Source    .    . use (man page)  . . implementation .
  293. . (file.h) . . (file.cc) .    . (file.3)        . . (file.doc)     .
  294. ............ .............    ................... ..................
  295.  
  296.  
  297. Figure 2
  298.  
  299. @title           Assign a title to the output files.
  300. @copyright       Put copyright info in output files.
  301. @code            Flag the following lines as code to be written to an
  302.                  output file
  303. @text            Flag the following lines as text that is not to be
  304.                  written to an output file.
  305. @specification   Start defining a specification.
  306. @class           Define a new class
  307. @base            Specify a base class for a previous class definition.
  308. @public          Specify a public interface to a class
  309. @protected       Specify a protected interface to a class
  310. @private         Specify a private interface to a class
  311. @requires        Specify member function requirements
  312. @effects         Specify member function effects
  313. @implementation  Start defining an implementation
  314. @inline          Define an inline member function
  315. @member          Define a member function
  316.  
  317.  
  318. Listing 1 (lcpp)
  319.  
  320. # @(#) lcpp 12feb90 (msh)
  321. # function timestamp: outputs the file creation timestamp
  322. # this function may not work on non-unix systems
  323. function timestamp( file ) {
  324.   "date" | getline d
  325.   print "// @(#) " file " created " d > file
  326. }
  327.  
  328. # function notice: outputs the title and do not revise
  329. # notice for the passed file.
  330. function notice( title, file ) {
  331.   print title > file
  332.   print "" > file
  333.   print "// This file generated from the input file " ARGV[1] > file
  334.   print "// DO NOT REVISE THIS FILE." > file
  335.   print "// To make revisions modify the original input file." > file
  336.   print "" > file
  337. }
  338.  
  339. # function members:  keep track of members by class and type
  340. # Entries are kept in the order defined.
  341. function members( type ) {
  342.   $1 = ""
  343.   if ( $2 ~ /@.*/ ) {
  344.     classNum = class[ substr($2,2) ]; $2 = ""
  345.   } else {
  346.     classNum = classCount
  347.   }
  348.   member[classNum,type,member[classNum,type]] = $0
  349.   ++member[classNum,type]
  350. }
  351.  
  352. # function error: print line number, error message,
  353. # and increase error counter
  354. function error( msg ) {
  355.   print "Line " NR ": " msg
  356.   errors++
  357. }
  358.  
  359. # function doMember: output members of a given type for a given class
  360. function doMembers( num, type ) {
  361.   if ( member[num,type] > 0 ) {
  362.     print type ":" > hOut
  363.     for (i = 0; i < member[num,type]; ++i) {
  364.       print " " member[num,type,i] > hOut
  365.     }
  366.   }
  367. }
  368.  
  369. # function doClass: outputs a class specification from
  370. # the internal class tables
  371. function doClass( num ) {
  372.   # output the class header
  373.   print "" > hOut
  374.   printf "class %s", className[num] > hOut
  375.   # Add any base classes.  Output the opening brace.
  376.   for ( i = 0; i < base[num]; ++i ) {
  377.     printf "%s", base[num,i] > hOut
  378.   }
  379.   print " {" > hOut
  380.   # output the various members
  381.   doMembers( num, "public" )
  382.   doMembers( num, "protected" )
  383.   doMembers( num, "private" )
  384.   # terminate the class.
  385.   print "};" > hOut
  386. }
  387.  
  388. # verify the correct number of arguments and build
  389. # the name of the output files
  390. BEGIN {
  391.   if (ARGC != 2) {
  392.     print "usage: " ARGV[0] " -f lcpp file"
  393.     exit 1
  394.   }
  395.   count = index(ARGV[1],".")
  396.   if (count == 0) {
  397.     hOut = ARGV[1] ".h"
  398.     ccOut = ARGV[1] ".cc"
  399.   } else {
  400.     hOut = substr(ARGV[1],1,count) "h"
  401.     ccOut = substr(ARGV[1],1,count) "cc"
  402.   }
  403.   timestamp(hOut); timestamp(ccOut)
  404. }
  405.  
  406. # @<anything>: turn off output whenever an @command is found
  407. $1 ~ /^@.*/ { outEnabled = 0 }
  408.  
  409. # @title: The title is written to both output files as a comment.
  410. # output remains off.
  411. $1 == "@title" {
  412.   $1 = "// title: "; notice( $0, hOut ); notice( $0, ccOut ); next }
  413.  
  414. # @copyright: Output is turned on so the following copyright info
  415. # is written to both output files.
  416. $1 == "@copyright" { hOutEnabled = 1; ccOutEnabled = 1; outEnabled = 1; next }
  417.  
  418. # @specification: Marker for the start of a specification.
  419. # direct output to the header file only, but keep output disabled
  420. $1 == "@specification" { hOutEnabled = 1; ccOutEnabled = 0; next }
  421.  
  422. # @text: Disable output (actually done above, just eat the @text)
  423. $1 == "@text" { next }
  424.  
  425. # @code: Enable output for the following lines.
  426. $1 == "@code" { outEnabled = 1; next }
  427.  
  428. # @class: look for class definition.  Verify the class name.
  429. # Start storing info in an array entry for the class.
  430. $1 == "@class" {
  431.   if ( NF != 2 ) {
  432.     error( "invalid class definition" )
  433.   } else {
  434.     if ( $2 in class ) {
  435.       error( "duplicate class name" )
  436.     } else {
  437.       ++classCount; classNum = classCount
  438.       class[$2] = classNum; className[classNum] = $2
  439.       base[classNum] = 0
  440.       member[classNum,"public"] = 0
  441.       member[classNum,"protected"] = 0
  442.       member[classNum,"private"] = 0
  443.     }
  444.   }
  445.   next
  446. }
  447.  
  448. # @base:  define a base for the named class.  If not class
  449. # named use the last class defined.  Add it to the base class
  450. # array for the appropriate class.
  451. $1 == "@base" {
  452.   if ( $2 ~ /^@.*/ ) {
  453.     classNum = class[ substr($2,2) ]; $2 = ""
  454.   } else {
  455.     classNum = classCount
  456.   }
  457.   if ( classNum ) {
  458.     $1 = base[classNum] == 0 ? ":" : ","
  459.     base[classNum,base[classNum]] = $0
  460.     ++base[classNum]
  461.   } else {
  462.     error( "no class for base definition" )
  463.   }
  464.   next
  465. }
  466.  
  467. # keep track of public entries by class.
  468. $1 == "@public" { members( "public" ); next }
  469.  
  470. # keep track of protected entries by class.
  471. $1 == "@protected" { members( "protected" ); next }
  472.  
  473. # keep track of private entries by class.
  474. $1 == "@private" { members( "private" ); next }
  475.  
  476. # process @requires.  Ignore for now.
  477. $1 == "@requires" { next; }
  478.  
  479. # process @effects. Ignore for now.
  480. $1 == "@effects" { next; }
  481.  
  482. # entering the implementation section of the input.  Set code output to go
  483. # to the cc file after dumping the classes.  Output remains off.
  484. $1 == "@implementation" {
  485.   for ( classNum = 1; classNum <= classCount; classNum++ ) {
  486.     doClass( classNum )
  487.   }
  488.   classCount = 0
  489.   hOutEnabled = 0
  490.   ccOutEnabled = 1
  491.   print "#include \"" hOut "\"" > ccOut
  492.   next
  493. }
  494.  
  495. # member function definition.  Enable output to the c file.
  496. $1 == "@member" { hOutEnabled = 0; ccOutEnabled = 1; outEnabled = 1; next }
  497.  
  498. # inline member function.  Enable output to the h file.
  499. $1 == "@inline" { hOutEnabled = 1; ccOutEnabled = 0; outEnabled = 1; next }
  500.  
  501. # check if an invalid @command was given and flag the line number
  502. $1 ~ /^@/ { error( "unknown command" ); next }
  503.  
  504. # if output is enabled for the header file write this line out
  505. outEnabled == 1 && hOutEnabled == 1 { print $0 > hOut }
  506.  
  507. # if output is enabled for the cc file write this line out
  508. outEnabled == 1 && ccOutEnabled == 1 { print $0 > ccOut }
  509.  
  510. END {
  511.   for ( classNum = 1; classNum <= classCount; classNum++ ) {
  512.     doClass( classNum )
  513.   }
  514.   close( hOut );
  515.   close( ccOut );
  516.   if ( errors ) {
  517.     print errors "error(s) found"
  518.     exit 1
  519.   } else {
  520.     print "generated " hOut " and " ccOut
  521.   }
  522. }
  523.  
  524. Listing 2 (test.lc)
  525.  
  526. @title Example Program
  527. This text does not go in either file.
  528. @copyright
  529. /*
  530.  * This class doesn't do anything.
  531.  */
  532. @text
  533. Note: Copyright output is to both files until
  534. the next @command
  535. @specification
  536. Code output is not enabled.  If you wish something
  537. to be written to the header file you must turn on
  538. code generation by using an @code
  539. @code
  540.  
  541. #include <stdio.h>
  542. @text
  543. stdio.h was included above as it is used by
  544. one of the inline functions.
  545. @class testClass
  546. This is where testClass is described.
  547. @private int dataMember;
  548. This is where dataMember is described.
  549. @public inline testClass();
  550. @requires
  551. The requirements, if any, of the testClass
  552. constructor.
  553. @effects
  554. The effects of calling the testClass constructor
  555. @text
  556. General text about the constructor.
  557. @public virtual ~testClass();
  558. @implementation
  559. Text describing implementation issues.
  560. @code
  561.  
  562. // this will be part of the .cc file
  563.  
  564. @text
  565. The next function is inline, so it will be added
  566. to the header file.  This assumes that the function
  567. has been declared inline above.
  568. @inline
  569. testClass::testClass()
  570. {
  571. @text
  572. Text can be added even in the middle of a function.
  573. Just use @code to start outputting code again.
  574. @code
  575.   printf( "testClass constructor\n" );
  576. }
  577. @text
  578. The next function is a member function.
  579. @member
  580. testClass::~testClass()
  581. {
  582.   // do something here
  583. }
  584.  
  585. Listing 3 (test.h)
  586.  
  587. // @(#) test.h created Thu Mar 29 17:56:47 PST 1990
  588. // title:  Example Program
  589.  
  590. // This file generated from the input file test.lc
  591. // DO NOT REVISE THIS FILE.
  592. // To make revisions modify the original input file.
  593.  
  594. /*
  595.  * This class doesn't do anything.
  596.  */
  597.  
  598. #include <stdio.h>
  599.  
  600. class testClass {
  601. public:
  602.     inline testClass();
  603.     virtual ~testClass();
  604. private:
  605.     int dataMember;
  606. };
  607. testClass::testClass()
  608. {
  609.     printf( "testClass constructor\n" );
  610. }
  611.  
  612. Listing 4 (test.cc)
  613.  
  614. // @(#) test.cc created Thu Mar 29 17:56:47 PST 1990
  615. // title:  Example Program
  616.  
  617. // This file generated from the input file test.lc
  618. // DO NOT REVISE THIS FILE.
  619. // To make revisions modify the original input file.
  620.  
  621. /*
  622.  * This class doesn't do anything.
  623.  */
  624. #include "test.h"
  625.  
  626. // this will be part of the .cc file
  627.  
  628. testClass::~testClass()
  629. {
  630. // do something here
  631. }
  632.